package com.whmall.service.crm.module.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.whmall.component.entity.dto.OperatorReqDTO;
import com.whmall.component.entity.dto.PageReqDTO;
import com.whmall.component.entity.dto.PageRspDTO;
import com.whmall.component.enumeration.AddressTypeEnum;
import com.whmall.component.util.FieldUtils;
import com.whmall.service.crm.entity.dto.company.*;
import com.whmall.service.crm.entity.dto.companyuser.CompanyUserAddressDTO;
import com.whmall.service.crm.module.company.dao.CompanyUserAddressMapper;
import com.whmall.service.crm.module.company.entity.CompanyUserAddressDO;
import com.whmall.service.crm.module.company.entity.qo.CompanyUserAddressQO;
import com.whmall.service.crm.module.company.service.CompanyUserAddressService;
import com.whmall.service.crm.module.companyuser.dao.CompanyUserMapper;
import com.whmall.service.crm.module.companyuser.entity.CompanyUserDO;
import com.whmall.service.crm.util.PageDTOHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CompanyUserAddressServiceImpl implements CompanyUserAddressService {

    @Autowired
    private CompanyUserAddressMapper companyUserAddressMapper;

    @Autowired
    private CompanyUserMapper companyUserMapper;

    @Override
    public CompanyUserAddressDTO getById(long id) {
        return BeanUtil.copyProperties(companyUserAddressMapper.selectById(id), CompanyUserAddressDTO.class);
    }

    @Transactional
    @Override
    public CompanyUserAddressAddRspDTO add(CompanyUserAddressAddReqDTO reqDTO) {
        //创建对象
        CompanyUserDO user = companyUserMapper.getById(reqDTO.getUserId());
        CompanyUserAddressDO address = new CompanyUserAddressDO();
        BeanUtils.copyProperties(reqDTO, address);
        address.setCompanyId(user.getCompanyId());
        Date now = new Date();
        if (Integer.valueOf(1).equals(address.getIsEnabled())) {
            address.setEnableId(reqDTO.getOperator().getOperatorId());
            address.setEnableType(reqDTO.getOperator().getOperatorType().getValue());
            address.setEnableTime(now);
        }
        Long addressCount = companyUserAddressMapper.selectCount(new LambdaQueryWrapper<CompanyUserAddressDO>()
                .eq(CompanyUserAddressDO::getDeleted, 0)
                .eq(CompanyUserAddressDO::getUserId, user.getId())
                .eq(CompanyUserAddressDO::getAddressType, reqDTO.getAddressType()));
        if (addressCount == 0) {
            address.setDefaultAddress(1);
        }
        address.setCreateId(reqDTO.getOperator().getOperatorId());
        address.setCreateType(reqDTO.getOperator().getOperatorType().getValue());
        address.setCreateTime(now);
        //排重
        if (isDuplicate(address)) {
            throw new IllegalArgumentException("已存在相同的地址信息");
        }
        //处理默认地址
        processDefault(address, true, reqDTO.getOperator());
        //保存
        companyUserAddressMapper.insertSelective(address);
        //生成收票地址
        if (AddressTypeEnum.ADDRESS_4_DELIVERY.getValue().equals(reqDTO.getAddressType())
                && Integer.valueOf(1).equals(reqDTO.getGenInvoiceAddress())) {
            //如果有错误提示信息，只返回提示信息不抛异常，业务上要求前面的操作能成功
            if (genInvoiceAddress(address.getId(), reqDTO.getOperator()) != 0) {
                return CompanyUserAddressAddRspDTO.builder().id(address.getId())
                        .msg("新增收货地址成功，生成收票地址失败，已存在相同的收票地址").build();
            }
        }
        return CompanyUserAddressAddRspDTO.builder().id(address.getId()).build();
    }

    @Transactional
    @Override
    public String update(CompanyUserAddressUpdateReqDTO reqDTO) {
        CompanyUserAddressDO addressOld = companyUserAddressMapper.selectById(reqDTO.getId());
        CompanyUserDO user = companyUserMapper.getById(reqDTO.getUserId());
        CompanyUserAddressDO address = new CompanyUserAddressDO();
        BeanUtils.copyProperties(reqDTO, address);
        address.setCompanyId(user.getCompanyId());
        address.setAddressType(addressOld.getAddressType());
        Date now = new Date();
        if (Integer.valueOf(1).equals(address.getIsEnabled())) {
            address.setEnableId(reqDTO.getOperator().getOperatorId());
            address.setEnableType(reqDTO.getOperator().getOperatorType().getValue());
            address.setEnableTime(now);
        }
        address.setUpdateId(reqDTO.getOperator().getOperatorId());
        address.setUpdateType(reqDTO.getOperator().getOperatorType().getValue());
        address.setUpdateTime(now);
        //排重
        if (isDuplicate(address)) {
            throw new IllegalArgumentException("已存在相同的地址信息");
        }
        //处理默认地址
        processDefault(address, true, reqDTO.getOperator());
        //保存
        companyUserAddressMapper.updateByIdSelective(address);
        //生成收票地址
        address = companyUserAddressMapper.selectById(reqDTO.getId());
        if (AddressTypeEnum.ADDRESS_4_DELIVERY.getValue().equals(address.getAddressType())
                && Integer.valueOf(1).equals(reqDTO.getGenInvoiceAddress())) {
            //如果有错误提示信息，只返回提示信息不抛异常，业务上要求前面的操作能成功
            if (genInvoiceAddress(address.getId(), reqDTO.getOperator()) != 0) {
                return "修改收货地址成功，生成收票地址失败，已存在相同的收票地址";
            }
        }
        return null;
    }

    @Transactional
    @Override
    public int genInvoiceAddress(Long id, OperatorReqDTO operator) {
        CompanyUserAddressDO address = companyUserAddressMapper.selectById(id);
        address.setId(null);
        address.setDefaultAddress(0);
        address.setAddressType(AddressTypeEnum.ADDRESS_4_INVOICE.getValue());
        address.setCreateId(operator.getOperatorId());
        address.setCreateType(operator.getOperatorType().getValue());
        address.setUpdateId(null);
        address.setUpdateTime(null);
        //排重
        if (isDuplicate(address)) {
            return -1;
        }
        //处理默认地址
        processDefault(address, false, operator);
        //保存
        companyUserAddressMapper.insertSelective(address);
        return 0;
    }

    @Transactional
    @Override
    public void remove(Long id, OperatorReqDTO operator) {
        CompanyUserAddressDO address = CompanyUserAddressDO.builder()
                .id(id)
                .deleted((int) (System.currentTimeMillis() / 1000))
                .updateId(operator.getOperatorId())
                .updateType(operator.getOperatorType().getValue())
                .updateTime(new Date())
                .build();
        int count = companyUserAddressMapper.updateByIdSelective(address);
        if (count != 1) {
            throw new IllegalArgumentException("未找到地址信息");
        }
    }

    @Transactional
    @Override
    public void setDefault(Long id, OperatorReqDTO operator) {
        CompanyUserAddressDO address = companyUserAddressMapper.selectById(id);
        if (Integer.valueOf(1).equals(address.getDefaultAddress())) {
            address.setDefaultAddress((int) (System.currentTimeMillis() / 1000));
        } else {
            address.setDefaultAddress(1);
        }
        //处理默认地址
        processDefault(address, true, operator);
        //保存
        address = CompanyUserAddressDO.builder()
                .id(address.getId())
                .defaultAddress(address.getDefaultAddress())
                .updateId(operator.getOperatorId())
                .updateType(operator.getOperatorType().getValue())
                .updateTime(new Date())
                .build();
        companyUserAddressMapper.updateByIdSelective(address);
    }

    @Override
    public List<CompanyUserAddressQueryRspDTO> list(CompanyUserAddressQueryReqDTO queryReqDTO) {
        CompanyUserAddressQO qo = new CompanyUserAddressQO();
        BeanUtils.copyProperties(queryReqDTO, qo);
        qo.setDeleted(0);
        return companyUserAddressMapper.listBy(qo).stream()
                .map(e -> {
                    CompanyUserAddressQueryRspDTO rspDTO = new CompanyUserAddressQueryRspDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    rspDTO.setDefaultAddress(FieldUtils.unwrapDefault(rspDTO.getDefaultAddress()));
                    return rspDTO;
                }).collect(Collectors.toList());
    }

    @SuppressWarnings("unchecked")
    @Override
    public PageRspDTO<CompanyUserAddressQueryRspDTO> list(PageReqDTO pageReqDTO, CompanyUserAddressQueryReqDTO reqDTO) {
        CompanyUserAddressQO qo = new CompanyUserAddressQO();
        BeanUtils.copyProperties(reqDTO, qo);
        qo.setDeleted(0);
        PageDTOHelper.startPage(pageReqDTO);
        List<CompanyUserAddressDO> address = companyUserAddressMapper.listBy(qo);
        PageRspDTO pageRspDTO = PageDTOHelper.toPageDTO(address);
        List<CompanyUserAddressQueryRspDTO> rspDTOs = address.stream()
                .map(e -> {
                    CompanyUserAddressQueryRspDTO rspDTO = new CompanyUserAddressQueryRspDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    rspDTO.setDefaultAddress(FieldUtils.unwrapDefault(rspDTO.getDefaultAddress()));
                    return rspDTO;
                }).collect(Collectors.toList());
        pageRspDTO.setRecords(rspDTOs);
        return pageRspDTO;
    }

    /**
     * 判断地址是否重复
     *
     * @param address
     * @return
     */
    private boolean isDuplicate(CompanyUserAddressDO address) {
        CompanyUserAddressQO qo = CompanyUserAddressQO.builder()
                .companyId(address.getCompanyId())
                .userId(address.getUserId())
                .addressType(address.getAddressType())
                .name(address.getName())
                .mobile(address.getMobile())
                .province(address.getProvince())
                .city(address.getCity())
                .district(address.getDistrict())
                .address(address.getAddress())
                .deleted(0)
                .build();
        List<CompanyUserAddressDO> addressList = companyUserAddressMapper.listBy(qo);
        if (!addressList.isEmpty() && addressList.get(0).getId().equals(address.getId())) {
            return false;
        }
        return addressList.size() > 0;
    }

    /**
     * 处理默认地址
     *
     * @param companyUserAddressDO
     * @param forceDefault         如果要设置为默认，是否强制设置
     * @param operator
     */
    private void processDefault(CompanyUserAddressDO companyUserAddressDO, boolean forceDefault
            , OperatorReqDTO operator) {
        if (companyUserAddressDO.getDefaultAddress() != 1) {//非默认
            if (companyUserAddressDO.getId() != null) {
                CompanyUserAddressDO oldAddresss = companyUserAddressMapper.selectById(companyUserAddressDO.getId());
                //如果原本就是非默认的，是否默认字段的值就不变化，有利于排序
                companyUserAddressDO.setDefaultAddress(oldAddresss.getDefaultAddress() != 1 ?
                        oldAddresss.getDefaultAddress() : (int) (System.currentTimeMillis() / 1000));
            } else {
                companyUserAddressDO.setDefaultAddress((int) (System.currentTimeMillis() / 1000));
            }
        } else {//默认
            CompanyUserAddressQO qo = CompanyUserAddressQO.builder()
                    .companyId(companyUserAddressDO.getCompanyId())
                    .userId(companyUserAddressDO.getUserId())
                    .addressType(companyUserAddressDO.getAddressType())
                    .defaultAddress(1)
                    .build();
            List<CompanyUserAddressDO> addresss = companyUserAddressMapper.listBy(qo);
            if (addresss.size() > 0) {
                if (forceDefault) {
                    //把原有默认记录设置为非默认
                    //通过唯一索引查询，只会有1条
                    CompanyUserAddressDO addressUpdate = CompanyUserAddressDO.builder()
                            .id(addresss.get(0).getId())
                            .defaultAddress((int) (System.currentTimeMillis() / 1000))
                            .updateId(operator.getOperatorId())
                            .updateType(operator.getOperatorType().getValue())
                            .updateTime(new Date())
                            .build();
                    companyUserAddressMapper.updateByIdSelective(addressUpdate);
                } else {
                    companyUserAddressDO.setDefaultAddress((int) (System.currentTimeMillis() / 1000));
                }
            }
        }
    }

}
